﻿using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;

namespace DataProcess
{
    namespace NetWork
    {
        public class BaseServer
        {
            protected List<Socket> AllClient = new List<Socket>();
            protected Dictionary<Socket, string> ClientID = new Dictionary<Socket, string>();
            protected Socket LocalHost;
            /// <summary>
            /// 获取SocketID
            /// </summary>
            /// <param name="socket"></param>
            /// <returns></returns>
            public string getID(Socket socket)
            {
                if (ClientID.ContainsKey(socket))
                {
                    return ClientID[socket];
                }
                else
                {
                    return socket.RemoteEndPoint.ToString();
                }
            }
            /// <summary>
            /// 设置SocketID
            /// </summary>
            /// <param name="socket"></param>
            /// <param name="id"></param>
            public void setID(Socket socket, string id)
            {
                if (ClientID.ContainsKey(socket))
                {
                    ClientID[socket] = id;
                }
                else
                {
                    ClientID.Add(socket, id);
                }
            }
            /// <summary>
            /// 获取已有的全部Clients
            /// </summary>
            public string AllClients
            {
                get
                {
                    string res = "";
                    foreach (Socket socket in AllClient)
                    {
                        res += getID(socket) + ";\n";
                    }
                    return res;
                }
            }
            /// <summary>
            /// 根据ID获取Socket
            /// </summary>
            /// <param name="key">目标ID</param>
            /// <returns></returns>
            public Socket GetSocket(string key)
            {
                if (ClientID.ContainsValue(key))
                {
                    int index = 0;
                    foreach (string p in ClientID.Values)
                    {
                        if (p.Equals(key))
                        {
                            break;
                        }
                        index++;
                    }
                    foreach (Socket socket in ClientID.Keys)
                    {
                        if (index == 0)
                        {
                            return socket;
                        }
                        index--;
                    }
                    return null;
                }
                else
                {
                    return null;
                }
            }
            /// <summary>
            /// 已有的客户端数
            /// </summary>
            public int ClientCount => AllClient.Count;
            /// <summary>
            /// 当客户端上线
            /// </summary>
            public event Action<Socket> OnClientONline;
            /// <summary>
            /// 当客户端被关闭
            /// </summary>
            public event Action<Socket> ClientClose;
            /// <summary>
            /// 当信息到达
            /// </summary>
            public event Action<Socket, string> OnMessageArrived;
            /// <summary>
            /// 
            /// </summary>
            /// <param name="iP">本地服务器IP,默认使用IPAddress.Any;即可</param>
            /// <param name="port">服务器端口</param>
            /// <param name="maxclient">最大排队连接</param>
            public BaseServer(IPAddress iP, int port, int maxclient = 10)
            {

                LocalHost = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                LocalHost.Bind(new IPEndPoint(iP, port));  //绑定IP地址：端口  
                LocalHost.Listen(maxclient);    //设定最多10个排队连接请求  
                Task.Run(delegate ()
                {
                    while (true)
                    {
                        Socket socket = LocalHost.Accept();
                        MesaageGot(socket);
                        AllClient.Add(socket);
                        OnClientONline(socket);
                    }
                });
            }
            /// <summary>
            ///绑定当信息到达时的事件
            /// </summary>
            /// <param name="socket"></param>
            public virtual void MesaageGot(Socket socket)
            {
                byte[] b;
                Task.Run(delegate ()
                {
                    long has = 0;
                    while (socket.Connected)
                    {
                        try
                        {
                            while (socket.Available <= has)
                            {
                            }
                            has = socket.Available;
                            socket.Receive(b = new byte[socket.Available], SocketFlags.Peek);
                            string now = Encoding.UTF8.GetString(b);
                            OnMessageArrived(socket, now);
                        }
                        catch
                        {
                            ClientOffLine(socket);
                        }

                    }
                    ClientOffLine(socket);
                });
            }

            private void ClientOffLine(Socket socket)
            {


                try
                {
                    ClientID.Remove(socket);
                    AllClient.Remove(socket);
                    ClientClose(socket);
                    socket.Close();
                }
                catch (Exception ex)
                {
                    System.Diagnostics.Debug.WriteLine(ex.Message);
                }

            }
            /// <summary>
            /// 给所有已知客户端发送消息
            /// </summary>
            /// <param name="text">被发送的信息</param>
            public void SendTOALL(string text)
            {
                for (int i = 0; i < AllClient.Count; i++)
                {
                    SendMessage(i, text);
                }
            }
            /// <summary>
            /// 发送信息，根据序号
            /// </summary>
            /// <param name="index">序号</param>
            /// <param name="message">发送的信息内容</param>
            public void SendMessage(int index, string message)
            {
                try
                {
                    AllClient[index].SendTo(Encoding.UTF8.GetBytes(message), AllClient[index].LocalEndPoint);
                }
                catch
                {
                    ClientOffLine(AllClient[index]);
                }
            }
            /// <summary>
            /// 发送信息
            /// </summary>
            /// <param name="socket">目标客户端</param>
            /// <param name="message">发送的信息</param>
            public void SendMessage(Socket socket, string message)
            {
                try
                {
                    socket.SendTo(Encoding.UTF8.GetBytes(message), socket.LocalEndPoint);
                }
                catch
                {
                    ClientOffLine(socket);
                }
            }
        }

    }
}
